package com.wan.core.event;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.wan.thread.actor.ActorExecutor;
import com.wan.util.cglib.FastClassUtil;
import net.sf.cglib.reflect.FastMethod;

import java.lang.reflect.Method;
import java.util.*;

public class EventBus {

    private static final Log log = LogFactory.get();
    private static final ActorExecutor actorExecutor;
    private static final Map<Class<? extends Event>, Map<FastMethod,Listener>> eventListenerMap;
    static {
        eventListenerMap = new HashMap<>();
        actorExecutor = new ActorExecutor(Runtime.getRuntime().availableProcessors() * 2, "event-bus");
    }

    /**
     * 注册事件监听
     */
    public static void addListener(Object listener){
        Method[] methods = listener.getClass().getDeclaredMethods();
        for (Method method : methods) {
            EventListener eventListener = method.getAnnotation(EventListener.class);
            if(eventListener == null){
                continue;
            }
            Class<?>[] parameterTypes = method.getParameterTypes();
            if(parameterTypes.length != 1) {
                throw new RuntimeException("事件监听方法参数错误，必须只有1个为Event子类的参数:" + method.toGenericString());
            }
            Class<?> paramType = parameterTypes[0];
            if (!Event.class.isAssignableFrom(paramType)){
                throw new RuntimeException("事件监听方法参数错误，必须只有1个为Event子类的参数:" + method.toGenericString());
            }
            //noinspection unchecked
            Class<? extends Event> eventType = (Class<? extends Event>) paramType;
            FastMethod fastMethod = FastClassUtil.getFastMethod(method);
            eventListenerMap.computeIfAbsent(eventType,type -> new HashMap<>())
                    .put(fastMethod,new Listener(listener,fastMethod,eventListener.async()));
        }
    }

    /**
     * 同步发送事件
     */
    public static void sendSync(Event event){
        Class<? extends Event> eventClass = event.getClass();
        Map<FastMethod,Listener> listeners = eventListenerMap.get(eventClass);
        if(listeners == null){
            return;
        }
        for (Listener listener : listeners.values()) {
            try {
                //强制异步执行
                if(listener.isAsync()){
                    actorExecutor.execute(listener.toActor(event));
                }else{
                    listener.call(event);
                }
            }catch (Exception e){
                log.error(e,"事件监听通知失败,event:{},listener:{}",event.getClass().getName(),listener.getObj().getClass().getName());
            }
        }
    }

    /**
     * 异步发送事件
     */
    public static void sendAsync(Event event){
        Class<? extends Event> eventClass = event.getClass();
        Map<FastMethod,Listener> listeners = eventListenerMap.get(eventClass);
        if(listeners == null){
            return;
        }
        for (Listener listener : listeners.values()) {
            try {
                actorExecutor.execute(listener.toActor(event));
            }catch (Exception e){
                log.error(e,"事件监听通知失败,event:{},listener:{}",event.getClass().getName(),listener.getObj().getClass().getName());
            }
        }
    }


}
